﻿using System;
using System.Text;
using System.Diagnostics;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Collections.Generic;
using Bovespa.Infra.Data;
using Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades;

namespace Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Dados
{
    /// <summary>
    /// Fornece operacoes de acesso a dados para a entidade de negocio "Artigo".
    /// </summary>
    public class Artigo
    {
        #region Campos

        private static int aplicacaoID = -1;        

        #endregion

        #region Properties

        private int AplicacaoID
        {
            get
            {
                if (-1 == aplicacaoID)
                {
                    System.Configuration.AppSettingsReader reader = new System.Configuration.AppSettingsReader();
                    aplicacaoID = (int)reader.GetValue("ApplicationInfraID", typeof(int));
                }
                return aplicacaoID;
            }
        }

        #endregion

        #region Metodos

        /// <summary>
        /// Recupera uma lista de entidades de negocio "Artigo" do banco de dados.
        /// </summary>
        public List<Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo> ConsultarArtigo()
        {
            List<Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo> listaArtigo = new List<Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo>();

            SqlDatabase conexao = new SqlDatabase(AplicacaoID);
            conexao.CreateStoredProcCommand("SPBASE_CONHECIMENTO_CO_TB_ARTIGO");

            using (IDataReader dados = conexao.ExecuteReader())
            {
                while (dados.Read())
                {
                    Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo artigo = new Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo();

                    int codigoIndice = dados.GetOrdinal("CD_ARTIGO");
                    artigo.Codigo = dados.GetInt64(codigoIndice);

                    int codigoProdutoIndice = dados.GetOrdinal("CD_PRODUTO");
                    if (!dados.IsDBNull(codigoProdutoIndice))
                    {
                        artigo.Produto.Codigo = dados.GetInt32(codigoProdutoIndice);
                    }

                    int codigoUsuarioIndice = dados.GetOrdinal("CD_USUARIO");
                    artigo.CodigoUsuario = dados.GetInt32(codigoUsuarioIndice);

                    int codigoVersaoIndice = dados.GetOrdinal("CD_VERSAO");
                    if (!dados.IsDBNull(codigoVersaoIndice))
                    {
                        artigo.Versao.Codigo = dados.GetInt32(codigoVersaoIndice);
                    }

                    int nomeTituloIndice = dados.GetOrdinal("NM_TITULO_ARTIGO");
                    artigo.NomeTitulo = dados.GetString(nomeTituloIndice);

                    int sintomaIndice = dados.GetOrdinal("DS_SINTOMA");
                    artigo.Sintoma = dados.GetString(sintomaIndice);

                    int solucaoIndice = dados.GetOrdinal("DS_SOLUCAO");
                    artigo.Solucao = dados.GetString(solucaoIndice);

                    listaArtigo.Add(artigo);
                }
            }
            return listaArtigo;
        }

        /// <summary>
        /// Recupera uma entidade de negocio "Artigo" do banco de dados.
        /// </summary>
        public Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo ObterArtigo(long id)
        {
            Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo artigo = new Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo();

            SqlDatabase conexao = new SqlDatabase(AplicacaoID);
            conexao.CreateStoredProcCommand("SPBASE_CONHECIMENTO_CO_TB_ARTIGO_POR_PK");
            conexao.AddInParameter("P_CD_ARTIGO", DbType.Int64, id);

            using (IDataReader dados = conexao.ExecuteReader())
            {
                if (dados.Read())
                {
                    int codigoIndice = dados.GetOrdinal("CD_ARTIGO");
                    artigo.Codigo = dados.GetInt64(codigoIndice);

                    int codigoProdutoIndice = dados.GetOrdinal("CD_PRODUTO");
                    if (!dados.IsDBNull(codigoProdutoIndice))
                    {
                        artigo.Produto.Codigo = dados.GetInt32(codigoProdutoIndice);
                        artigo.Produto.Nome = dados.GetString(dados.GetOrdinal("NM_PRODUTO"));
                    }

                    int codigoUsuarioIndice = dados.GetOrdinal("CD_USUARIO");
                    artigo.CodigoUsuario = dados.GetInt32(codigoUsuarioIndice);

                    int codigoVersaoIndice = dados.GetOrdinal("CD_VERSAO");
                    if (!dados.IsDBNull(codigoVersaoIndice))
                    {
                        artigo.Versao.Codigo = dados.GetInt32(codigoVersaoIndice);
                        artigo.Versao.Nome = dados.GetString(dados.GetOrdinal("NM_VERSAO"));
                    }

                    int nomeTituloIndice = dados.GetOrdinal("NM_TITULO_ARTIGO");
                    artigo.NomeTitulo = dados.GetString(nomeTituloIndice);

                    int sintomaIndice = dados.GetOrdinal("DS_SINTOMA");
                    artigo.Sintoma = dados.GetString(sintomaIndice);

                    int solucaoIndice = dados.GetOrdinal("DS_SOLUCAO");
                    artigo.Solucao = dados.GetString(solucaoIndice);

                }
            }
            return artigo;
        }

        /// <summary>
        /// Persiste uma entidade de negocio "Artigo" no banco de dados.
        /// </summary>
        public long InserirArtigo(Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo artigo)
        {
            SqlDatabase conexao = new SqlDatabase(AplicacaoID);
            conexao.CreateStoredProcCommand("SPBASE_CONHECIMENTO_IN_TB_ARTIGO");

            long codigoArtigo;

            conexao.AddInParameter("P_CD_PRODUTO", DbType.Int32, artigo.Produto.Codigo);

            conexao.AddInParameter("P_CD_USUARIO", DbType.Int32, artigo.CodigoUsuario);
            
            conexao.AddInParameter("P_CD_VERSAO", DbType.Int32, artigo.Versao.Codigo);

            if (artigo.NomeTitulo != null)
            {
                conexao.AddInParameter("P_NM_TITULO_ARTIGO", DbType.String, artigo.NomeTitulo);
            }
            if (artigo.Sintoma != null)
            {
                conexao.AddInParameter("P_DS_SINTOMA", DbType.String, artigo.Sintoma);
            }
            if (artigo.Solucao != null)
            {
                conexao.AddInParameter("P_DS_SOLUCAO", DbType.String, artigo.Solucao);
            }
            conexao.AddOutParameter("P_CD_ARTIGO_RET", DbType.Int64, 8);

            conexao.ExecuteNonQuery();

            codigoArtigo = Convert.ToInt64(conexao.GetParameterValue("P_CD_ARTIGO_RET"));

            return codigoArtigo;
        }

        /// <summary>
        /// Remove uma entidade de negocio "Artigo" do banco de dados.
        /// </summary>
        public void ExcluirArtigo(long id)
        {
            SqlDatabase conexao = new SqlDatabase(AplicacaoID);
            conexao.CreateStoredProcCommand("SPBASE_CONHECIMENTO_DL_TB_ARTIGO");
            conexao.AddInParameter("P_CD_ARTIGO", DbType.Int64, id);
            conexao.ExecuteNonQuery();
        }

        /// <summary>
        /// Atualiza uma entidade de negocio "Artigo" no banco de dados.
        /// </summary>
        public void AtualizarArtigo(Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo artigo)
        {
            SqlDatabase conexao = new SqlDatabase(AplicacaoID);
            conexao.CreateStoredProcCommand("SPBASE_CONHECIMENTO_UP_TB_ARTIGO");
            conexao.AddInParameter("P_CD_ARTIGO", DbType.Int64, artigo.Codigo);

            conexao.AddInParameter("P_CD_PRODUTO", DbType.Int32, artigo.Produto.Codigo);

            conexao.AddInParameter("P_CD_USUARIO", DbType.Int32, artigo.CodigoUsuario);

            conexao.AddInParameter("P_CD_VERSAO", DbType.Int32, artigo.Versao.Codigo);
            
            if (artigo.NomeTitulo != null)
            {
                conexao.AddInParameter("P_NM_TITULO_ARTIGO", DbType.String, artigo.NomeTitulo);
            }
            if (artigo.Sintoma != null)
            {
                conexao.AddInParameter("P_DS_SINTOMA", DbType.String, artigo.Sintoma);
            }
            if (artigo.Solucao != null)
            {
                conexao.AddInParameter("P_DS_SOLUCAO", DbType.String, artigo.Solucao);
            }
            conexao.ExecuteNonQuery();
        }

        /// <summary>
        /// Busca as palavras-chaves retornando os id's das palavras encontradas
        /// </summary>
        public List<long> RetornarIdsPalavrasChaves(string filtroSqlPesquisa)
        {
            SqlDatabase conexao = new SqlDatabase(AplicacaoID);
            DbDataReader dr = conexao.ExecuteReader(CommandType.Text, string.Format("select * from dbo.tb_palavra_chave where {0}", filtroSqlPesquisa)) as DbDataReader;
            if (dr.HasRows)
            {
                List<long> retorno = new List<long>();
                while (dr.Read())
                    retorno.Add(dr.GetInt64(dr.GetOrdinal("cd_palavra_chave")));
                return retorno;
            }
            else
            {
                return new List<long>();
            }            
        }

        /// <summary>
        /// Retorna artigos pelas palavras-chaves
        /// </summary>
        public List<Entidades.Artigo> RetornarArtigosPalavrasChaves(string filtroSqlPesquisa)
        {
            StringBuilder sbSql = new StringBuilder();
            sbSql.AppendLine("select distinct ");
            sbSql.AppendLine("    a.cd_artigo, ");
            sbSql.AppendLine("    p.nm_produto, ");
            sbSql.AppendLine("    v.nm_versao, ");
            sbSql.AppendLine("    a.nm_titulo_artigo, ");
            sbSql.AppendLine("    a.ds_sintoma, ");
            sbSql.AppendLine("    a.ds_solucao ");
            sbSql.AppendLine("from ");
            sbSql.AppendLine("    dbo.tb_produto p ");
            sbSql.AppendLine("        join dbo.tb_versao v on ");
            sbSql.AppendLine("            p.cd_produto = v.cd_produto ");
            sbSql.AppendLine("        join dbo.tb_artigo a on  ");
            sbSql.AppendLine("            v.cd_produto = a.cd_produto and ");
            sbSql.AppendLine("            v.cd_versao = a.cd_versao ");
            sbSql.AppendLine("        join dbo.tb_artigo_palavra_chave apc on ");
            sbSql.AppendLine("            a.cd_artigo = apc.cd_artigo ");
            sbSql.AppendFormat("where {0}", filtroSqlPesquisa);
            SqlDatabase conexao = new SqlDatabase(AplicacaoID);
            DbDataReader dr = conexao.ExecuteReader(CommandType.Text, sbSql.ToString()) as DbDataReader;
            if (dr.HasRows)
            {
                List<Entidades.Artigo> retorno = new List<Entidades.Artigo>();
                while (dr.Read())
                {
                    Entidades.Artigo item = new Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.Artigo();
                    item.Codigo = Convert.ToInt32(dr["cd_artigo"]);
                    item.Produto = new Entidades.Produto();
                    item.Produto.Nome = dr.GetString(dr.GetOrdinal("nm_produto"));
                    item.Versao = new Entidades.Versao();
                    item.Versao.Nome = dr.GetString(dr.GetOrdinal("nm_versao"));
                    item.NomeTitulo = dr.GetString(dr.GetOrdinal("nm_titulo_artigo"));
                    item.Sintoma = dr.GetString(dr.GetOrdinal("ds_sintoma"));
                    item.Solucao = dr.GetString(dr.GetOrdinal("ds_solucao"));
                    retorno.Add(item);
                }
                return retorno;
            }
            else
            {
                return new List<Entidades.Artigo>();
            }
        }

        /// <summary>
        /// Persiste palavras chaves no banco de dados e as relaciona com os artigos.
        /// </summary>
        public void InserirPalavraChave(Bovespa.Sinacor.Servico.BaseConhecimento.Artigo.Entidades.PalavraChave palavraChave)
        {
            SqlDatabase conexao = new SqlDatabase(AplicacaoID);
            conexao.CreateStoredProcCommand("SPBASE_CONHECIMENTO_IN_TB_PALAVRA_CHAVE");

            conexao.AddInParameter("P_CD_ARTIGO", DbType.Int64, palavraChave.CodigoArtigo);
            conexao.AddInParameter("P_NM_PALAVRA_CHAVE", DbType.String, palavraChave.NomePalavraChave);
            
            conexao.ExecuteNonQuery();
        }

        #endregion
    }
}

